-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Warn when coercing NAN to other types #19573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
d43ae9a
to
bfb238b
Compare
8da693f
to
729488f
Compare
AWS x86_64 (c7i.24xl)
Laravel 12.2.0 demo app - 100 consecutive runs, 50 warmups, 100 requests (sec)
Symfony 2.7.0 demo app - 100 consecutive runs, 50 warmups, 100 requests (sec)
Wordpress 6.2 main page - 100 consecutive runs, 20 warmups, 20 requests (sec)
bench.php - 100 consecutive runs, 10 warmups, 2 requests (sec)
|
@@ -7728,7 +7728,14 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32 | |||
if_double = ir_IF(ir_EQ(type, ir_CONST_U8(IS_DOUBLE))); | |||
ir_IF_TRUE(if_double); | |||
} | |||
ref = ir_NE(jit_Z_DVAL(jit, op1_addr), ir_CONST_DOUBLE(0.0)); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to avoid calling zend_is_true()
during compilation above when the value is a const nan, otherwise we emit two warnings here: (during tracing, then while compiling the trace)
echo (bool)NAN;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done a check, but now the function JIT doesn't emit a warning :/
* Those optimizations are not safe if the other operand end up being NAN | ||
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Triggered a benchmark to check the effect of this: valgrind shows no regression (changes are under 0.0x%).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do wonder if this is not actually a problem for switch cases too now that I think of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be worth it to check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it seems I completely broke switch statements...
<?php
$nan = fdiv(0, 0);
switch ($nan) {
case true:
echo "true";
break;
case false:
echo "false";
break;
}
?>
Returns nothing now, even without opcache :|
729488f
to
37c74ce
Compare
37c74ce
to
7c29b7f
Compare
if (Z_MODE(op1_addr) == IS_CONST_ZVAL) { | ||
if (zend_is_true(Z_ZV(op1_addr))) { | ||
zval *op1 = Z_ZV(op1_addr); | ||
/* NAN Value must cause a warning to be emitted */ | ||
// TODO function JIT does not emit warning | ||
if ((Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1))) || zend_is_true(op1)) { | ||
always_true = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's because the cast gets optimized to a constant true when setting always_true = 1
. You need to skip the if (Z_MODE(op1_addr) == IS_CONST_ZVAL) {
branch entirely when it's nan.
@@ -16,6 +16,7 @@ | |||
* +----------------------------------------------------------------------+ | |||
*/ | |||
|
|||
#include "../../../Zend/zend_types.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#include "../../../Zend/zend_types.h" | |
#include "Zend/zend_types.h" |
* Those optimizations are not safe if the other operand end up being NAN | ||
* as BOOL/BOOL_NOT will warn which IS_EQUAL/IS_NOT_EQUAL do not. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be worth it to check
RFC: https://wiki.php.net/rfc/warnings-php-8-5#coercing_nan_to_other_types